package utils

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"github.com/pkg/errors"

	"github.com/upmio/horus-polymerizer/log"
	"github.com/upmio/horus-server/structs"
	// "strconv"
	"strings"
	//	"time"
)

//CommonRes is exported
//common response for http request
type CommonRes struct {
	Err string `json:"Err"`
}

//RegisterToHsrv is exported
// 向horus-server 发送注册请求
/*func RegisterToHsrv(port int, ip, name, hsrvs, check string) {

	defer func() {
		if err := recover(); err != nil {
			log.Infof("RegisterToHsrv PANIC:%v", err)
		}
	}()
	time.Sleep(2 * time.Second)

	//	netslice := strings.Split(nets, "#")
	hsrvslice := strings.Split(hsrvs, "#")
	cfg := []structs.ColletorConfig{}

	node := structs.ColletorConfig{
		//		NetWork:      netslice,
		Endpoint:     name,
		Type:         "host",
		MetricTags:   name,
		ColletorIp:   ip,
		ColletorPort: port,
		CheckType:    check,
	}

	cfg = append(cfg, node)

	cfgstr, _ := json.Marshal(cfg)

	for {
		for _, hsrv := range hsrvslice {
			fmt.Println("hsrv:", hsrv)
			if hsrv == "" {
				continue
			}

			uri := "http://" + hsrv + "/v1/agent/register"
			//bytes.NewBuffer 必须在这，不能在for外圈
			body := bytes.NewBuffer(cfgstr)
			log.Infof("try register to %s. body:%s", uri, body.String())
			res := httpPost(uri, body)

			if res.Err != "" {
				log.Errorf("register to %s fail: %s.", uri, res.Err)
				continue
			}

			log.Infof("register ok", uri)
			return

		}
		log.Infof(" register fail.wait 30s to retry.")
		time.Sleep(30 * time.Second)
	}
}*/

//ComponentRegisterToServer is exported
// 向horus-server 发送注册请求
func ComponentRegisterToServer(node, name, tag, check, hsrvs string) error {

	defer func() {
		if err := recover(); err != nil {
			log.Error("ComponentRegisterToServer get panic:", err)
		}
	}()

	cfg := structs.ComponentRegister{
		Name:      node,
		HostName:  node,
		Tag:       tag,
		Type:      "platform",
		CheckType: check,
	}

	cfgstr, err := json.Marshal(cfg)
	if err != nil {
		return err
	}

	hsrvslice := strings.Split(hsrvs, "#")
	for _, hsrv := range hsrvslice {
		fmt.Println("hsrv:", hsrv)
		if hsrv == "" {
			continue
		}

		uri := "http://" + hsrv + "/v1/components"
		body := bytes.NewBuffer(cfgstr)
		log.Infof("try component register to  %s. body:%s", uri, body.String())
		err := httpPost(uri, body)

		if err != nil {
			log.Errorf(" component register to %s fail: %s.", uri, err)
			continue
		}

		log.Infof("component register ok", uri)
		return nil

	}

	return errors.New("component register fail ")

}

//ComponentUnRegisterToServer is exported
//// 向horus-server 发送注销请求
func ComponentUnRegisterToServer(name, hsrvs string) error {

	defer func() {
		if err := recover(); err != nil {
			log.Infof("ComponentUnRegisterToServer PANIC:%v", err)
		}
	}()

	hsrvslice := strings.Split(hsrvs, "#")
	/*cfg := structs.DeregisterComponentConfig{
		Name: name,
	}*/

	//cfgstr, _ := json.Marshal(cfg)

	for _, hsrv := range hsrvslice {
		fmt.Println("hsrv:", hsrv)
		if hsrv == "" {
			continue
		}

		uri := "http://" + hsrv + "/v1/components/" + name
		req, err := http.NewRequest("DELETE", uri, nil)
		if err != nil {
			log.Errorf(" component unregister to %s fail: %s.", uri, err)
			continue
		}
		req.Header.Set("Content-Type", "application/json")
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			log.Errorf("deregister to Horus response:%s", err)
			continue
		}
		if resp.StatusCode != http.StatusNoContent {
			res := struct {
				Err string
			}{}

			err := json.NewDecoder(resp.Body).Decode(&res)
			if err != nil {
				log.Errorf("decode response body:%d", resp.StatusCode)
				continue
			}
		}

		log.Infof("component unregister ok", uri)
		return nil
	}
	return errors.New("component unregister fail ")
}

//UnRegisterToHsrv is exported
// 向horus-server 发送注销请求
/*func UnRegisterToHsrv(name, hsrvs string) {
	defer func() {
		if err := recover(); err != nil {
			log.Infof("UnRegisterToHsrv PANIC:%v", err)
		}
	}()

	hsrvslice := strings.Split(hsrvs, "#")
	cfg := []structs.DeregisterColletorConfig{}

	node := structs.DeregisterColletorConfig{
		Endpoint: name,
	}
	cfg = append(cfg, node)

	cfgstr, _ := json.Marshal(cfg)

	for _, hsrv := range hsrvslice {

		fmt.Println("hsrv:", hsrv)
		if hsrv == "" {
			continue
		}
		body := bytes.NewBuffer(cfgstr)
		uri := "http://" + hsrv + "/v1/agent/deregister"
		log.Infof("try unregister to %s.data: %s", uri, body.String())
		res := httpPost(uri, body)

		if res.Err != "" {
			log.Errorf("unregister to %s fail: %s.", uri, res.Err)
			continue
		}

		log.Infof("unregister ok ")
		return
	}
}*/

func httpPost(uri string, body *bytes.Buffer) error {

	defer func() {
		if err := recover(); err != nil {
			log.Infof("httpPost PANIC:%v", err)
		}
	}()

	response, err := http.Post(uri, "", body)

	if err != nil {
		return errors.Wrap(err, "http post err")
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		buf := bytes.NewBuffer(nil)
		io.Copy(buf, response.Body)
		res := struct {
			Err string
		}{}

		err := json.NewDecoder(response.Body).Decode(&res)
		if err != nil {
			return errors.Wrapf(err, "%d:decode response body", response.StatusCode)
		}
		return errors.Errorf("StatusCode:%d,Error:%s", response.StatusCode, res.Err)
		/*return errors.Wrap()
			return &CommonRes{Err: fmt.Sprintf("Unexpected response code:%d (%s)", response.StatusCode, buf.String())}
		}

		res := &structs.ResponseHead{}
		if err := json.NewDecoder(response.Body).Decode(res); err != nil {
			return &CommonRes{Err: "parse the :response.Body fail: " + err.Error()}*/
	}

	return nil
}
